<script lang="ts" setup>
import {
  assignUserRole,
  getAllRole,
  getUserRoleList
} from "@/api/modules/system";
import type { RoleVO, UserRoleAssignParams } from "@/api/modules/system/types";
import { isEmpty } from "@pureadmin/utils";
import { ElMessage } from "element-plus";
import { PlusColumn, PlusDrawerForm } from "plus-pro-components";
import { computed, onMounted, ref, watch } from "vue";

defineOptions({
  name: "user-role-assign"
});

const props = defineProps({
  visible: {
    type: Boolean,
    default: false
  },
  userInfo: {
    type: Object,
    required: true
  }
});

const emit = defineEmits(["close", "success"]);

const visible = ref(props.visible);
const loading = ref(false);
const allRole = ref<RoleVO[]>([]);
const selectedRoleIds = ref<string[]>([]);
const originalRoleIds = ref<string[]>([]);

// 计算属性：选中角色数量
const selectedCount = computed(() => selectedRoleIds.value.length);
const totalCount = computed(() => allRole.value.length);

// 监听visible变化，当抽屉打开时加载数据
watch(
  () => props.visible,
  newVal => {
    visible.value = newVal;
    if (newVal && props.userInfo?.id) {
      loadData();
    }
  }
);

// 监听userInfo变化，当用户信息变化时重新加载数据
watch(
  () => props.userInfo,
  newVal => {
    if (visible.value && newVal?.id) {
      loadData();
    }
  },
  { deep: true }
);

const columns: PlusColumn[] = [
  {
    label: "用户名",
    width: 120,
    prop: "role",
    hasLabel: false
  }
];

// 加载所有数据
async function loadData() {
  loading.value = true;
  try {
    // 同时加载所有角色和用户已分配的角色
    await Promise.all([loadAllRoles(), loadUserRoles()]);
  } catch (error) {
    ElMessage.error("加载角色数据失败");
  } finally {
    loading.value = false;
  }
}

// 加载所有角色
async function loadAllRoles() {
  try {
    const res = await getAllRole();

    // 处理不同的数据结构情况
    if (res.data && Array.isArray(res.data)) {
      // 直接是数组的情况
      allRole.value = res.data;
    } else if (res.data && typeof res.data === "object") {
      // 是对象的情况，尝试获取其中的数组
      if ("records" in res.data && Array.isArray(res.data.records)) {
        allRole.value = res.data.records;
      } else if (Array.isArray(res.data)) {
        allRole.value = res.data;
      }
    }
  } catch (error) {
    ElMessage.error("加载所有角色失败");
  }
}

// 加载用户已分配的角色
async function loadUserRoles() {
  if (!props.userInfo?.id) return;

  try {
    const res = await getUserRoleList(props.userInfo.id);

    // 处理不同的数据结构情况
    let userRoles: RoleVO[] = [];

    if (res.data && Array.isArray(res.data)) {
      // 直接是数组的情况
      userRoles = res.data;
    } else if (res.data && typeof res.data === "object") {
      // 是对象的情况，尝试获取其中的数组
      if ("records" in res.data && Array.isArray(res.data.records)) {
        userRoles = res.data.records;
      }
    }

    selectedRoleIds.value = userRoles
      .map(role => role.id)
      .filter(id => !isEmpty(id)) as string[];

    originalRoleIds.value = [...selectedRoleIds.value];
  } catch (error) {
    ElMessage.error("加载用户角色失败");
  }
}

// 切换角色选择状态
function toggleRoleSelection(roleId: string) {
  const index = selectedRoleIds.value.indexOf(roleId);
  if (index === -1) {
    selectedRoleIds.value.push(roleId);
  } else {
    selectedRoleIds.value.splice(index, 1);
  }
}

// 检查角色是否被选中
function isRoleSelected(roleId: string): boolean {
  // 确保比较的类型一致
  const isSelected = selectedRoleIds.value.includes(roleId);
  return isSelected;
}

// 处理checkbox变化
function handleCheckboxChange(
  roleId: string,
  checked: boolean | string | number
) {
  const isChecked = Boolean(checked);
  if (isChecked && !isRoleSelected(roleId)) {
    // 如果选中且不在选中列表中，则添加
    toggleRoleSelection(roleId);
  } else if (!isChecked && isRoleSelected(roleId)) {
    // 如果取消选中且在选中列表中，则移除
    toggleRoleSelection(roleId);
  }
}

// 提交角色分配
async function handleSubmit() {
  if (!props.userInfo?.id) return;

  loading.value = true;
  try {
    // 检查是否有变更
    const hasChanges = !areArraysEqual(
      selectedRoleIds.value,
      originalRoleIds.value
    );

    if (!hasChanges) {
      ElMessage.info("角色分配未变更");
      handleClose();
      return;
    }

    // 调用API分配角色
    const params: UserRoleAssignParams = {
      userId: props.userInfo.id,
      roleIds: selectedRoleIds.value
    };

    const res = await assignUserRole(params);

    if (res.success) {
      ElMessage.success("角色分配成功");
      emit("success");
      handleClose();
    } else {
      ElMessage.error(res.message || "角色分配失败");
    }
  } catch (error) {
    ElMessage.error("角色分配失败");
  } finally {
    loading.value = false;
  }
}

// 关闭抽屉
function handleClose() {
  // 重置状态
  selectedRoleIds.value = [];
  originalRoleIds.value = [];
  emit("close");
}

// 比较两个数组是否相等
function areArraysEqual(arr1: string[], arr2: string[]): boolean {
  if (arr1.length !== arr2.length) return false;

  const sorted1 = [...arr1].sort();
  const sorted2 = [...arr2].sort();

  return sorted1.every((val, idx) => val === sorted2[idx]);
}

// 全选角色
function selectAllRoles() {
  // 将所有角色ID添加到selectedRoleIds中
  selectedRoleIds.value = allRole.value.map(role => role.id);

  // 显示提示
  ElMessage.success(`已全选 ${selectedCount.value} 个角色`);
}

// 清空选择
function clearSelection() {
  selectedRoleIds.value = [];

  // 显示提示
  ElMessage.info("已清空所有选择");
}

// 初始化
onMounted(() => {
  if (visible.value && props.userInfo?.id) {
    loadData();

    // 添加延迟检查，确保角色选择状态正确
    setTimeout(() => {
      // 强制更新
      selectedRoleIds.value = [...selectedRoleIds.value];
    }, 500);
  }
});
</script>

<template>
  <div>
    <PlusDrawerForm
      v-model:visible="visible"
      size="25%"
      :form="{ columns }"
      :title="`用户角色分配: ${props.userInfo?.username || ''}`"
      :loading="loading"
      @close="handleClose"
      @confirm="handleSubmit"
    >
      <template #plus-field-role>
        <div v-if="allRole.length === 0">暂无可分配角色</div>
        <div v-else class="w-full">
          <!-- 操作按钮 -->
          <div class="role-actions">
            <div class="role-buttons">
              <el-button type="primary" size="small" @click="selectAllRoles"
                >全选</el-button
              >
              <el-button type="warning" size="small" @click="clearSelection"
                >清空</el-button
              >
            </div>
            <div class="role-counter">已选择: {{ selectedCount }} 个角色</div>
          </div>

          <!-- 角色列表 -->
          <div class="role-list">
            <div
              v-for="role in allRole"
              :key="role.id"
              class="role-item"
              @click="toggleRoleSelection(role.id)"
            >
              <el-checkbox
                :model-value="isRoleSelected(role.id)"
                @click.stop
                @change="val => handleCheckboxChange(role.id, val)"
              >
                <div class="role-info">
                  <div class="role-name">
                    {{ role.name }}
                    <span class="role-code">{{ role.code }}</span>
                  </div>
                  <div class="role-desc">{{ role.description }}</div>
                </div>
              </el-checkbox>
            </div>
          </div>
        </div>
      </template>
    </PlusDrawerForm>
  </div>
</template>

<style scoped>
.role-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 5px;
  margin-bottom: 10px;
}

.role-buttons {
  display: flex;
  gap: 8px;
}

.role-counter {
  font-size: 14px;
  color: #606266;
}

.role-list {
  overflow: hidden auto;
}

.role-item {
  display: block;
  padding: 8px 0;
  cursor: pointer;
  border-bottom: 1px solid #f0f0f0;
}

.role-item:last-child {
  border-bottom: none;
}

.role-info {
  display: flex;
  flex-direction: column;
}

.role-name {
  font-weight: 500;
}

.role-code {
  margin-left: 8px;
  font-size: 12px;
  color: #8c8c8c;
}

.role-desc {
  margin-top: 4px;
  font-size: 12px;
  color: #8c8c8c;
}
</style>
